package com.bookcloud.java21.chapter15;

import java.io.*;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/** Data utility class for generating mock student data 数据工具类，用于生成模拟学生数据 */
public class SignDataUtil {

  // 存放所有学生数据
  private static final Map<String, Student> studentMap = new HashMap<>();

  // 存放学生历史签到记录
  private static List<Student> historyList = new ArrayList<>();

  // 今天的学生签到数据
  private static List<Student> todayList = null;

  private static final String[] FIRST_NAMES = {
    "张", "王", "李", "刘", "陈", "杨", "赵", "黄", "周", "吴",
    "徐", "孙", "胡", "朱", "高", "林", "何", "郭", "马", "罗"
  };

  private static final String[] LAST_NAMES = {
    "伟", "芳", "娜", "秀英", "敏", "静", "丽", "强", "磊", "军",
    "洋", "勇", "艳", "杰", "娟", "涛", "明", "超", "秀兰", "霞",
    "平", "刚", "桂英", "建华", "文", "华", "金凤", "志强", "春梅", "海燕"
  };

  public static List<Student> getAllSignList() {
    // 检测今天的数据在历史的清单是否存在

    // 合并今天学生签到的列表
    historyList.addAll(todayList);
    return historyList;
  }

  /**
   * Generate mock student data list 生成模拟学生数据列表
   *
   * @param count Number of students to generate
   * @return List of Student objects
   */
  public static List<Student> generateMockStudentData(int count) {
    List<Student> students = new ArrayList<>();
    Random random = new Random();
    LocalDate today = LocalDate.now();
    LocalDateTime now = LocalDateTime.now();

    for (int i = 1; i <= count; i++) {
      String name = generateRandomName(random);
      // 获取年月日字符串
      String dateStr = today.toString();
      dateStr = dateStr.replace("-", "");
      String stuNo = dateStr + (100 + i);

      // Random sign-in status (70% chance of being signed in)
      int status = random.nextDouble() < 0.7 ? 1 : 0;

      // 生成签到日期字符串， 格式如：20250807
      String signDate = dateStr;
      // 生成签到时间字符串， 格式如：141223
      String signTime = now.format(java.time.format.DateTimeFormatter.ofPattern("HHmmss"));
      Student student = new Student(name, stuNo, status, signDate, signTime);
      students.add(student);
    }

    return students;
  }

  /** Generate random Chinese name 生成随机中文姓名 */
  private static String generateRandomName(Random random) {
    String firstName = FIRST_NAMES[random.nextInt(FIRST_NAMES.length)];
    String lastName = LAST_NAMES[random.nextInt(LAST_NAMES.length)];

    // Sometimes add a second character to the last name
    if (random.nextDouble() < 0.3) {
      String secondLastName = LAST_NAMES[random.nextInt(LAST_NAMES.length)];
      return firstName + lastName + secondLastName;
    }

    return firstName + lastName;
  }

  /** Get default student data for today's sign-in 获取今日签到的默认学生数据 */
  public static List<Student> getTodaySignData() {

    return todayList; // Generate 30 students by default
  }

  /** Get students who have signed in today 获取今日已签到的学生 */
  public static List<Student> getSignedInStudents() {
    return getTodaySignData().stream().filter(student -> student.getStatus() == 1).toList();
  }

  /** Get students who haven't signed in today 获取今日未签到的学生 */
  public static List<Student> getNotSignedInStudents() {
    return getTodaySignData().stream().filter(student -> student.getStatus() == 0).toList();
  }

  /** Get historical data for a specific date 获取指定日期的历史数据 */
  public static List<Student> getHistoricalDataForDate_bak(String dateStr) {
    List<Student> historicalData = new ArrayList<>();
    Random random = new Random(dateStr.hashCode()); // Use date as seed for consistent data

    // Generate consistent data based on date for 24 students
    for (int i = 1; i <= 24; i++) {
      String name = generateRandomName(random);
      String stuNo = dateStr.replace("-", "") + (100 + i);

      // Random sign-in status (about 70% attendance rate)
      int status = random.nextDouble() < 0.7 ? 1 : 0;

      // Generate sign date and time strings
      String signDate = status == 1 ? dateStr.replace("-", "") : "";
      String signTime = status == 1 ? "083000" : ""; // Default 08:30:00 for signed students

      Student student = new Student(name, stuNo, status, signDate, signTime);
      historicalData.add(student);
    }

    return historicalData;
  }

  // 查询历史的签到情况 20250903 格式
  public static List<Student> getHistoricalDataForDate(String dateStr) {
    // 日期格式化
    String localDateStr = dateStr.replace("-", "");
    return historyList.stream()
        .filter(student -> student.getSignDate().equals(localDateStr))
        .toList();
  }

  /** Get student statistics for report 获取学生统计数据用于报表 */
  public static List<SignStaticsReportUI.StudentStatistics> getStudentStatistics_bak() {
    List<SignStaticsReportUI.StudentStatistics> statisticsList = new ArrayList<>();
    Random random = new Random(42); // Fixed seed for consistent statistics

    // Generate statistics for 24 students (to fill the 8x3 table)
    for (int i = 1; i <= 24; i++) {
      String name = generateRandomName(random);

      // Generate random but realistic attendance data
      int totalDays = 10; // Assume 10 days period
      int signedDays = random.nextInt(9) + 2; // 2-10 signed days
      int absentDays = totalDays - signedDays;

      SignStaticsReportUI.StudentStatistics stats =
          new SignStaticsReportUI.StudentStatistics(name, signedDays, absentDays);
      statisticsList.add(stats);
    }

    return statisticsList;
  }

  /** Get student statistics for report 获取学生统计数据用于报表 */
  public static List<SignStaticsReportUI.StudentStatistics> getStudentStatistics() {
    List<SignStaticsReportUI.StudentStatistics> statisticsList = new ArrayList<>();

    // 统计所有学生的签到情况
    // 1. 按学生编号分组统计
    Map<String, List<Student>> studentSignMap =
        historyList.stream().collect(Collectors.groupingBy(Student::getStuNo));

    // 2. 计算每个学生的签到统计
    for (Map.Entry<String, List<Student>> entry : studentSignMap.entrySet()) {
      String stuNo = entry.getKey();
      List<Student> studentRecords = entry.getValue();

      if (studentRecords.isEmpty()) continue;

      // 获取学生姓名（取第一条记录的姓名）
      String studentName = studentRecords.get(0).getName();

      // 统计签到次数和未签到次数
      int signedDays = 0;
      int absentDays = 0;

      for (Student record : studentRecords) {
        if (record.getStatus() == 1) {
          // 签到的总天数
          signedDays++;
        } else {
          // 未签到的总天数
          absentDays++;
        }
      }

      // 创建学生统计对象
      SignStaticsReportUI.StudentStatistics stats =
          new SignStaticsReportUI.StudentStatistics(studentName, signedDays, absentDays);
      statisticsList.add(stats);
    }

    // 3. 按学生编号排序
    statisticsList.sort(
        (s1, s2) -> {
          // 通过姓名找到对应的学生编号进行排序
          String stuNo1 = "";
          String stuNo2 = "";
          for (Map.Entry<String, Student> studentEntry : studentMap.entrySet()) {
            if (studentEntry.getValue().getName().equals(s1.getName())) {
              stuNo1 = studentEntry.getKey();
            }
            if (studentEntry.getValue().getName().equals(s2.getName())) {
              stuNo2 = studentEntry.getKey();
            }
          }
          return stuNo1.compareTo(stuNo2);
        });

    return statisticsList;
  }

  /** Get student chart data for statistical charts 获取学生图表数据用于统计图表 */
  public static List<SignStatisticalChartUI.StudentChartData> getStudentChartData() {
    List<SignStatisticalChartUI.StudentChartData> chartDataList = new ArrayList<>();
    
    // 统计所有学生的签到情况
    // 1. 按学生编号分组统计
    Map<String, List<Student>> studentSignMap = historyList.stream()
        .collect(Collectors.groupingBy(Student::getStuNo));
    
    // 2. 计算每个学生的签到统计
    for (Map.Entry<String, List<Student>> entry : studentSignMap.entrySet()) {
      String stuNo = entry.getKey();
      List<Student> studentRecords = entry.getValue();
      
      if (studentRecords.isEmpty()) continue;
      
      // 获取学生姓名（取第一条记录的姓名）
      String studentName = studentRecords.get(0).getName();
      
      // 统计签到次数和未签到次数
      int signedDays = 0;
      int absentDays = 0;
      
      for (Student record : studentRecords) {
        if (record.getStatus() == 1) {
          signedDays++;
        } else {
          absentDays++;
        }
      }
      
      // 创建学生图表数据对象
      SignStatisticalChartUI.StudentChartData chartData = 
          new SignStatisticalChartUI.StudentChartData(studentName, signedDays, absentDays);
      chartDataList.add(chartData);
    }
    
    // 3. 按学生编号排序
    chartDataList.sort((c1, c2) -> {
      // 通过姓名找到对应的学生编号进行排序
      String stuNo1 = "";
      String stuNo2 = "";
      for (Map.Entry<String, Student> studentEntry : studentMap.entrySet()) {
        if (studentEntry.getValue().getName().equals(c1.getName())) {
          stuNo1 = studentEntry.getKey();
        }
        if (studentEntry.getValue().getName().equals(c2.getName())) {
          stuNo2 = studentEntry.getKey();
        }
      }
      return stuNo1.compareTo(stuNo2);
    });

    return chartDataList;
  }

  // 初始化信息
  public static void loadData() {
    // 加载学生信息
    readStudentInfo();
    // 读取签到数据
    readSignData();
    // 解析历史签到数据是否存在今天数据
    parseSignDataAndUpdateTodayList();
  }

  /** 解析历史签到数据是否存在今天数据及更新今天签到数据 */
  private static void parseSignDataAndUpdateTodayList() {
    // 解析历史签到数据是否存在今天数据
    String today = LocalDate.now().toString().replace("-", "");
    // 过滤出今天的签到数据
    List<Student> todayList2 =
        historyList.stream().filter(student -> student.getSignDate().equals(today)).toList();
    // 如果存在今天的签到数据，就更新内存中的数据
    if (!todayList2.isEmpty()) {
      // 更新todayList
      todayList = todayList2;
    } else {
      // 没有今天的签到数据，就生成今天的签到数据
      if (todayList == null) {
        // todayList = generateMockStudentData(24);
        todayList = new ArrayList<>();
        // 通过文件生成签到数据，内存里面取学生数据
        studentMap
            .entrySet()
            .forEach(
                entry -> {
                  // 生成今日学生签到数据
                  Student student = entry.getValue();
                  // 生成签到日期
                  String signDate = LocalDate.now().toString().replace("-", "");
                  // 实例一个学生对象
                  Student todayStudent =
                      new Student(student.getName(), student.getStuNo(), 0, signDate, "");
                  todayList.add(todayStudent);
                });
        // 存入签到历史列表中
        historyList.addAll(todayList);
      }
    }
  }

  // 读取学生的信息
  public static void readStudentInfo() {
    // 文件名称 student_info.txt
    String fileDir = "D:\\dev-work\\Java-Work\\java21-lesson\\com\\bookcloud\\java21\\chapter15\\";
    String fileName = fileDir + "student_info.txt";
    // 读取文件
    try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
      String line;
      while ((line = reader.readLine()) != null) {
        // 解析每一行数据
        String[] parts = line.split(",");
        if (parts.length == 2) {
          String name = parts[0];
          String stuNo = parts[1];
          // 学生的元数据存储到map集合，系统启动就加载到内存
          studentMap.put(stuNo, new Student(name, stuNo, 0, "", ""));
        }
      }
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  // 读取签到数据
  public static void readSignData() {
    // 签到数据文件名称 sign_data.csv
    String fileDir = "D:\\dev-work\\Java-Work\\java21-lesson\\com\\bookcloud\\java21\\chapter15\\";
    String fileName = fileDir + "sign_data.csv";
    // 读取文件
    try (BufferedReader reader = new BufferedReader(new FileReader(fileName))) {
      String line;
      // 马云恒, 2025001,1,2025-09-01,2025-09-01 8:30:20
      while ((line = reader.readLine()) != null) {
        // 解析每一行数据
        String[] parts = line.split(",");
        if (parts.length == 5) {
          String name = parts[0];
          String stuNo = parts[1];
          int status = Integer.parseInt(parts[2]);
          String signDate = parts[3];
          String signTime = parts[4];
          // 学生的签到数据存储到list集合，系统启动就加载到内存
          historyList.add(new Student(name, stuNo, status, signDate, signTime));
        }
      }
    } catch (IOException e) {
      // e.printStackTrace();
    }
  }

  // 写入签到数据
  public static void writeSignData() {
    // 签到数据文件名称 sign_data.csv
    // 文件名称 sign_data.csv
    String fileDir = "D:\\dev-work\\Java-Work\\java21-lesson\\com\\bookcloud\\java21\\chapter15\\";
    String fileName = fileDir + "sign_data.csv";
    // historyList列表数据去重关键字：学生编号+签到日期
    List<Student> storeList =
        historyList.stream()
            .distinct()
            .sorted(Comparator.comparing(Student::getSignDate).thenComparing(Student::getStuNo))
            .collect(Collectors.toList());

    // 写入文件
    try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) {
      for (Student student : storeList) {
        String signTime = student.getSignTime();
        // 签到时间为空，就写入空字符串
        if (signTime == null || signTime.isEmpty()) {
          signTime = "#";
        }
        writer.write(
            student.getName()
                + ","
                + student.getStuNo()
                + ","
                + student.getStatus()
                + ","
                + student.getSignDate()
                + ","
                + signTime);
        writer.newLine();
      }
    } catch (IOException e) {
      // e.printStackTrace();
    }
  }
}
